from info import db
from info.constants import HOME_PAGE_MAX_NEWS
from info.models import News, Comment, CommentLike, User
from info.utils.common import verify_login
from info.utils.response_code import RET, error_map
from . import news_blue
from flask import request, render_template, session, jsonify, g, current_app, abort


# 详情页面的展示
@news_blue.route("/<int:news_id>")
@verify_login
def detail(news_id):
    """这个路由主要实现了三个功能:
    1.显示详情页面的点击排行榜
    2.文章详情
    """
    """右边热门新闻排序"""
    # 根据新闻点击量来进行倒序,只要前10
    user = g.user
    news_model = News.query.order_by(News.clicks.desc()).limit(HOME_PAGE_MAX_NEWS)

    # 定义一个list,用来放前十的新闻
    news_list = []
    for news in news_model:
        news_list.append(news.to_dict())

    """展示文章详情"""
    # 这个news=None只是为了不不会报警告
    news = None
    try:
        news = News.query.get(news_id)
    except Exception as e:
        current_app.logger.error(e)
        abort(404)

    if not news:
        # 返回数据未找到的页面
        abort(404)

    # 新闻点击量加1
    news.clicks += 1

    """文章收藏"""
    if not user:  # 如果用户没有登录就不能使用收藏功能
        return jsonify(errno=RET.SESSIONERR, errmsg=error_map.get(RET.SESSIONERR))

    # 1.判断是否收藏该新闻,默认不收藏为False
    is_collected = False

    is_followed = False

    # 查询当前新闻作者的所有粉丝

    if g.user:
        if news in g.user.collection_news:
            is_collected = True

    if news.user and user:
        # 如果当前新闻作者在当前用户的关注列表中
        if news.user in user.followed:
            is_followed = True

    # 1.查询当前新闻的所有评论
    comment_list = Comment.query.filter(Comment.news_id == news_id).all()

    # 2.获取到所有评论点赞的数据
    # 当前用户点赞的评论
    comments = []

    # 该新闻所有点赞的用户
    comments_list_ids = []

    # 2.1查询用户点赞了那些评论
    comments = CommentLike.query.filter(CommentLike.user_id == g.user.id).all()

    # 2.2取出来所有点赞的id
    comments_list_ids = [comment_like.comment_id for comment_like in comments]

    # 2.3判断用户是否点赞该评论
    comment_dict_list = []

    # 遍历取出当前新闻的所有评论
    for item in comment_list:
        # 评论对象调用to_dict转换成一个字典
        comment_dict = item.to_dict()

        # 所有评论默认是没有点赞
        comment_dict["is_like"] = False

        # 判断用户是否有点赞该评论
        if item.id in comments_list_ids:
            comment_dict["is_like"] = True
        comment_dict_list.append(comment_dict)

    data = {
        "news_list": news_list,  # 右边新闻排序
        "news": news.to_dict(),  # 文章详情
        "is_collected": is_collected,  # 文章收藏
        "comments": comment_dict_list,  # 点赞
        "is_followed": is_followed,  # 作者关注
        "user_info": user.to_dict() if user else None  # 判断用户是否登录

    }

    return render_template("news/detail.html", data=data)


# 收藏功能接口
@news_blue.route("/news_collect", methods=["POST"])
@verify_login
def news_collect():
    """收藏功能接口"""
    # 获取用户是否登录,因为当前接口是针对收藏的,如果未登录就不能收藏
    user = g.user
    if not user:
        return jsonify(errno=RET.SESSIONERR, errmsg=error_map.get(RET.SESSIONERR))

    # 获取需要收藏的新闻id
    news_id = request.json.get("news_id")

    # 获取用户的动作,是否收藏
    action = request.json.get("action")

    # 查询当前要收藏的新闻是哪条
    news = News.query.get(news_id)

    # 判断是否收藏
    if action == "collect":
        user.collection_news.append(news)
    else:
        user.collection_news.remove(news)

    db.session.commit()
    return jsonify(errno=RET.OK, errmsg=error_map.get(RET.OK))


# 评论
@news_blue.route("/news_comment", methods=["POST"])
@verify_login
def news_comment():
    """评论
    在进行这个接口的书写的时候,先要进行用户登录的判断
    1.获取用户新闻id,评论内容
    2.根据获取的新闻id在数据库中查询出是哪个条新闻被评论了
    3.进行数据库添加操作
    """
    if not g.user:
        return jsonify(errno=RET.SESSIONERR, errmsg=error_map.get(RET.SESSIONERR))

    # 1.获取用户新闻id,评论内容
    news_id = request.json.get("news_id")
    comment_str = request.json.get("comment")
    parent_id = request.json.get("parent_id")

    if not all([news_id, comment_str, parent_id]):
        return jsonify(errno=RET.PARAMERR, errmsg="参数不够")
    # 2.根据获取的新闻id在数据库中查询出是哪个条新闻被评论了
    try:
        news = News.query.get(news_id)

    except Exception as a:
        current_app.logger.error(a)
        return jsonify(errno=RET.DBERR, errmsg=error_map.get(RET.DBERR))

    if not news:
        return jsonify(errno=RET.NODATA, errmsg="该新闻不存在 ")
    # 3.进行数据库添加操作
    comment = Comment()
    comment.user_id = g.user.id
    comment.news_id = news_id
    comment.content = comment_str

    # 判断一下是否有子评论
    if parent_id:
        comment.parent_id = parent_id

    db.session.add(comment)
    db.session.commit()
    return jsonify(errno=RET.OK, errmsg=error_map.get(RET.OK), data=comment.to_dict())


# 点赞
@news_blue.route("/comment_like", methods=["POST"])
@verify_login
def comment_like():
    """
    1.获取评论id,新闻id,还有是否已经点赞
    2.根据用户id和评论id综合判断是否点赞了
    :return:
    """
    user = g.user
    if not g.user:
        return jsonify(errno=RET.SESSIONERR, errmsg=error_map.get(RET.SESSIONERR))

    # 1.获取前端数据
    comment_id = request.json.get("comment_id")
    news_id = request.json.get("news_id")
    action = request.json.get("action")

    # 2.从数据库查询出是哪条评论
    comment = Comment.query.get(comment_id)

    comment_like = CommentLike.query.filter(CommentLike.comment_id == comment_id,
                                            CommentLike.user_id == user.id).first()
    if action == "add":
        # 点赞功能
        if not comment_like:
            # 查询出来的comment_like为空,用户执行点赞
            comment_like = CommentLike()
            comment_like.comment_id = comment_id
            comment_like.user_id = user.id

            db.session.add(comment_like)
            comment.like_count += 1

    else:
        # 有值,执行取消点赞
        if comment_like:
            db.session.delete(comment_like)
            comment.like_count -= 1

    db.session.commit()
    return jsonify(errno=RET.OK, errmsg=error_map.get(RET.OK))


# 关注取关接口
@news_blue.route("/followed_user", methods=["POST"])
@verify_login
def followed_user():
    """关注/取关"""
    if not g.user:
        return jsonify(errno=RET.SESSIONERR, errmsg=error_map.get(RET.SESSIONERR))

    # 获取用户参数和前端js传来的action值
    user_id = request.json.get("user_id")
    action = request.json.get("action")

    # 判断参数的正确
    if not all([user_id, action]):
        return jsonify(errno=RET.PARAMERR, errmsg=error_map.get(RET.PARAMERR))

    if action not in ("follow", "unfollow"):
        return jsonify(errno=RET.PARAMERR, errmsg=error_map.get(RET.PARAMERR))

    # 查询关注的用户信息
    try:
        target_user = User.query.get(user_id)
    except Exception as a:
        current_app.logger.error(a)
        return jsonify(errno=RET.DBERR, errmsg=error_map.get(RET.DBERR))

    if not target_user:
        return jsonify(errno=RET.NODATA, errmsg="未查询到用户数据")

    # 操作逻辑
    if action == "follow":
        if target_user.followers.filter(User.id == g.user.id).count() > 0:
            return jsonify(errno=RET.DATAEXIST, errmsg="当前已关注")
        target_user.followers.append(g.user)

    else:
        if target_user.followers.filter(User.id == g.user.id).count() > 0:
            target_user.followers.remove(g.user)

    # 保存数据
    try:
        db.session.commit()
    except Exception as b:
        current_app.logger.error(b)
        return jsonify(errno=RET.DBERR, errmsg="数据保存错误 ")

    return jsonify(errno=RET.OK, errmsg="操作成功")
